home *** CD-ROM | disk | FTP | other *** search
- /*
- File: MoreBBLog.c
-
- Contains: Module to log debug traces to BBEdit.
-
- Written by: Quinn
-
- Copyright: Copyright © 2000 by Apple Computer, Inc., all rights reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
-
- <4> 27/3/00 Quinn Add some more coercions from basic types to text. Don't assert
- if we can't AESend to BBEdit because BBEdit isn't running.
- <3> 20/3/00 Quinn Added coercions from built-in types to typeText to make
- descriptor logging more useful. Changed BBLogDesc to bypass
- Str255 limit.
- <2> 3/9/00 gaw API changes for MoreAppleEvents
- <1> 6/3/00 Quinn First checked in.
- */
-
- /////////////////////////////////////////////////////////////////
-
- // MoreIsBetter Setup
-
- #include "MoreSetup.h"
-
- // Mac OS Interfaces
-
- #include <AERegistry.h>
- #include <PLStringFuncs.h>
- #include <TextUtils.h>
- #include <Aliases.h>
-
- // MIB Prototypes
-
- #include "MoreAppleEvents.h"
- #include "MoreMemory.h"
-
- // Our Prototypes
-
- #include "MoreBBLog.h"
-
- /////////////////////////////////////////////////////////////////
-
- #if MORE_DEBUG
-
- static AECoercePtrUPP gBasicToTextCoerceUPP; // -> BasicToTextCoerceProc
-
- static pascal OSErr BasicToTextCoerceProc(DescType typeCode, const void *dataPtr, Size dataSize, DescType toType, SInt32 handlerRefCon, AEDesc *result)
- // A coercion handler to convert some basic Apple event types
- // to text. I added these types on demand, as I noticed that my
- // MoreOSL test program needed them.
- {
- #pragma unused(handlerRefCon)
- OSStatus err;
- ccntTokenRecPtr tokenData;
- AEDesc tokenAsText;
- Handle resultH;
- AliasHandle aliasH;
- Str63 tmpStr63;
- Str255 tmpStr;
- Str255 tmpStr2;
- FSSpecPtr fssP;
-
- MoreAssertQ(toType == typeText);
- MoreAssertQ(result != nil);
-
- MoreAENullDesc(result);
-
- switch (typeCode) {
- case typeNull:
- case typeCurrentContainer:
- case typeObjectBeingExamined:
- // You’d think that the following assert would be useful, but it fires all the time.
- // MoreAssertQ(dataPtr == nil);
- MoreAssertQ(dataSize == 0);
- err = AECreateDesc(typeText, &typeCode, sizeof(typeCode), result);
- break;
-
- case typeToken:
- MoreAssertQ(dataSize == sizeof(ccntTokenRecord));
- MoreAssertQ(dataPtr != nil);
-
- // The data for a token is a ccntTokenRecord. We extract the data,
- // then coerce the embedded descriptor to text, then add a header
- // that identifies the token as a token.
-
- MoreAENullDesc(&tokenAsText);
- resultH = nil;
-
- tokenData = (ccntTokenRecPtr) dataPtr;
- err = AECoerceDesc(&tokenData->token, typeText, &tokenAsText);
- if (err == noErr) {
- err = MoreAECopyDescriptorDataToHandle(&tokenAsText, &resultH);
- }
- if (err == noErr) {
- // Add the string "'toke-'" to the front of the handle.
- (void) Munger(resultH, 0, nil, 0, "'toke'-", 7);
- err = MemError();
- }
- if (err == noErr) {
- HLock(resultH);
- err = AECreateDesc(typeText, *resultH, GetHandleSize(resultH), result);
- }
-
- MoreAEDisposeDesc(&tokenAsText);
- if (resultH != nil) {
- DisposeHandle(resultH);
- MoreAssertQ(MemError() == noErr);
- }
- break;
-
- case typeAbsoluteOrdinal:
- MoreAssertQ(dataSize == sizeof(DescType));
- err = AECreateDesc(typeText, dataPtr, sizeof(DescType), result);
- break;
-
- case typeAlias:
- aliasH = nil;
-
- err = PtrToHand(dataPtr, (Handle *) &aliasH, dataSize);
- if (err == noErr) {
- err = GetAliasInfo(aliasH, asiAliasName, tmpStr63);
- }
- if (err == noErr) {
- PLstrcpy(tmpStr, "\palias(");
- PLstrcat(tmpStr, tmpStr63);
- PLstrcat(tmpStr, "\p)");
- err = AECreateDesc(typeText, &tmpStr[1], tmpStr[0], result);
- }
-
- if (aliasH != nil) {
- DisposeHandle( (Handle) aliasH );
- }
- break;
-
- case typeFSS:
- MoreAssertQ(dataPtr != nil);
- MoreAssertQ(dataSize == sizeof(FSSpec));
-
- fssP = (FSSpecPtr) dataPtr;
-
- PLstrcpy(tmpStr, "\pfss(");
- PLstrcat(tmpStr, fssP->name);
- PLstrcat(tmpStr, "\p)");
-
- err = AECreateDesc(typeText, &tmpStr[1], tmpStr[0], result);
- break;
-
- case typeBoolean:
- if ( *((Boolean *) dataPtr) ) {
- err = AECreateDesc(typeText, "true", 4, result);
- } else {
- err = AECreateDesc(typeText, "false", 5, result);
- }
- break;
-
- case typeTrue:
- err = AECreateDesc(typeText, "typeTrue", 8, result);
- break;
-
- case typeFalse:
- err = AECreateDesc(typeText, "typeFalse", 9, result);
- break;
-
- case typeQDPoint:
- PLstrcpy(tmpStr, "\pPoint(");
- NumToString( ((PointPtr) dataPtr)->h, tmpStr2);
- PLstrcat(tmpStr, tmpStr2);
- PLstrcat(tmpStr, "\p, ");
- NumToString( ((PointPtr) dataPtr)->v, tmpStr2);
- PLstrcat(tmpStr, tmpStr2);
- PLstrcat(tmpStr, "\p)");
-
- err = AECreateDesc(typeText, &tmpStr[1], tmpStr[0], result);
- break;
-
- case typeQDRectangle:
- PLstrcpy(tmpStr, "\pRect(");
- NumToString( ((RectPtr) dataPtr)->left, tmpStr2);
- PLstrcat(tmpStr, tmpStr2);
- PLstrcat(tmpStr, "\p, ");
- NumToString( ((RectPtr) dataPtr)->top, tmpStr2);
- PLstrcat(tmpStr, tmpStr2);
- PLstrcat(tmpStr, "\p, ");
- NumToString( ((RectPtr) dataPtr)->right, tmpStr2);
- PLstrcat(tmpStr, tmpStr2);
- PLstrcat(tmpStr, "\p, ");
- NumToString( ((RectPtr) dataPtr)->bottom, tmpStr2);
- PLstrcat(tmpStr, tmpStr2);
- PLstrcat(tmpStr, "\p)");
-
- err = AECreateDesc(typeText, &tmpStr[1], tmpStr[0], result);
- break;
-
- default:
- MoreAssertQ(false);
- err = errAECoercionFail;
- break;
- }
-
- return err;
- }
-
- static AECoerceDescUPP gRecordToTextCoerceUPP; // -> RecordToTextCoerceProc
-
- static pascal OSErr RecordToTextCoerceProc(const AEDesc *fromDesc, DescType toType, long handlerRefCon, AEDesc *toDesc)
- // A coercion handler to convert lists, records, and other things
- // coercible to records, to text.
- {
- #pragma unused(handlerRefCon)
- OSStatus err;
- Handle result;
- AEDesc fromDescAsRecord;
- SInt32 itemIndex;
- SInt32 itemCount;
- AEKeyword thisKeyword;
- AEDesc thisElement;
- AEDesc thisElementAsText;
- Size textSize;
-
- MoreAssertQ(fromDesc != nil);
- MoreAssertQ(toType == typeText);
- MoreAssertQ(toDesc != nil);
-
- MoreAENullDesc(toDesc);
- MoreAENullDesc(&fromDescAsRecord);
-
- // Create a handle for the resulting text.
-
- result = NewHandle(0);
- err = MoreMemError(result);
-
- // If the incoming data is a record or a list, we handle it natively
- // so just duplicate it into the fromDescAsRecord. OTOH, if the incoming
- // data is something weird (an object specifier, say), use AECoerceDesc to
- // coerce it to a record.
-
- if (err == noErr) {
- if (fromDesc->descriptorType == typeAERecord || fromDesc->descriptorType == typeAEList) {
- err = AEDuplicateDesc(fromDesc, &fromDescAsRecord);
- } else {
- err = AECoerceDesc(fromDesc, typeAERecord, &fromDescAsRecord);
- }
- }
-
- // Iterate through each element in the record/list, coercing the element
- // to text and appending its text to the handle.
-
- if (err == noErr) {
- err = AECountItems(&fromDescAsRecord, &itemCount);
- }
- if (err == noErr) {
- err = PtrAndHand("{", result, 1);
- for (itemIndex = 1; itemIndex <= itemCount; itemIndex++) {
- MoreAENullDesc(&thisElement);
- MoreAENullDesc(&thisElementAsText);
-
- err = AEGetNthDesc(&fromDescAsRecord, itemIndex, typeWildCard, &thisKeyword, &thisElement);
- if (err == noErr) {
- err = AECoerceDesc(&thisElement, typeText, &thisElementAsText);
- // While writing this code, I spent lots of time figuring out
- // exactly what type of data couldn’t be coerced to text and then
- // filling in that particular coercion. The following assert
- // helps detect these problems quickly.
- MoreAssertQ(err != errAECoercionFail);
- }
-
- // If we’re iteratintg through a record, the keyword is meaningful
- // so add it to the output handle.
-
- if (err == noErr && fromDescAsRecord.descriptorType == typeAERecord) {
- err = PtrAndHand("'", result, 1);
- if (err == noErr) {
- err = PtrAndHand(&thisKeyword, result, sizeof(thisKeyword));
- }
- if (err == noErr) {
- err = PtrAndHand("':", result, 2);
- }
- }
-
- // Grow the handle to make room for the text for this element,
- // then copy the text to the handle.
-
- if (err == noErr) {
- textSize = AEGetDescDataSize(&thisElementAsText);
- SetHandleSize(result, GetHandleSize(result) + textSize);
- err = MemError();
- }
- if (err == noErr) {
- HLock(result);
- err = AEGetDescData(&thisElementAsText, (*result) + GetHandleSize(result) - textSize, textSize);
- HUnlock(result);
- }
-
- // If we’re not the last element, add a separator.
-
- if (err == noErr && itemIndex < itemCount) {
- err = PtrAndHand(", ", result, 2);
- }
-
- MoreAEDisposeDesc(&thisElement);
- MoreAEDisposeDesc(&thisElementAsText);
-
- if (err != noErr) {
- break;
- }
- }
- }
- if (err == noErr) {
- err = PtrAndHand("}", result, 1);
- }
-
- // Create a descriptor containing the data from the text handle.
-
- if (err == noErr) {
- HLock(result);
- err = AECreateDesc(typeText, *result, GetHandleSize(result), toDesc);
- }
-
- // Clean up.
-
- if (result != nil) {
- DisposeHandle(result);
- MoreAssertQ(MemError() == noErr);
- }
- MoreAEDisposeDesc(&fromDescAsRecord);
-
- return err;
- }
-
- static void InstallTextCoercionHandlers(void)
- // This routine installs a bunch of coercion handles for
- // coercing various common data types to text. By adding these
- // coercions, we increase the utility of the rest of MoreBBLog,
- // which relies on being able to coerce various descriptors to text.
- {
- OSStatus junk;
-
- // First install all the basic coercions.
-
- gBasicToTextCoerceUPP = NewAECoercePtrUPP(BasicToTextCoerceProc);
- MoreAssertQ(gBasicToTextCoerceUPP != nil);
-
- junk = AEInstallCoercionHandler(typeNull, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeObjectBeingExamined, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeCurrentContainer, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeToken, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeAbsoluteOrdinal, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeAlias, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeFSS, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeBoolean, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeTrue, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeFalse, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeQDPoint, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeQDRectangle, typeText, (AECoercionHandlerUPP) gBasicToTextCoerceUPP, 0, false, false);
- MoreAssertQ(junk == noErr);
-
- // Then install the coercions for lists, records, and things coercible
- // to records.
-
- gRecordToTextCoerceUPP = NewAECoerceDescUPP(RecordToTextCoerceProc);
- MoreAssertQ(gRecordToTextCoerceUPP != nil);
-
- junk = AEInstallCoercionHandler(typeAERecord, typeText, (AECoercionHandlerUPP) gRecordToTextCoerceUPP, 0, true, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeAEList, typeText, (AECoercionHandlerUPP) gRecordToTextCoerceUPP, 0, true, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeAppleEvent, typeText, (AECoercionHandlerUPP) gRecordToTextCoerceUPP, 0, true, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeObjectSpecifier, typeText, (AECoercionHandlerUPP) gRecordToTextCoerceUPP, 0, true, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeRangeDescriptor, typeText, (AECoercionHandlerUPP) gRecordToTextCoerceUPP, 0, true, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeCompDescriptor, typeText, (AECoercionHandlerUPP) gRecordToTextCoerceUPP, 0, true, false);
- MoreAssertQ(junk == noErr);
-
- junk = AEInstallCoercionHandler(typeLogicalDescriptor, typeText, (AECoercionHandlerUPP) gRecordToTextCoerceUPP, 0, true, false);
- MoreAssertQ(junk == noErr);
- }
-
- static const OSType kBBEditCreator = 'R*ch';
-
- static UInt32 gIndent; // records the number of levels of indent, as controlled by BBLogIndent etc
- static Boolean gLogging; // determines whether logging is enabled (true) or not (false)
-
- extern pascal void BBLogStart(Boolean logging)
- // See comment in header file.
- {
- OSStatus err;
- AppleEvent theEvent;
- AppleEvent junkReply;
- DescType cDoc;
-
- // Start up by installing our coercion handles. This enables the rest
- // of the routines to provide much nicer output.
-
- InstallTextCoercionHandlers();
-
- gIndent = 0;
- gLogging = logging;
- if (gLogging) {
-
- // Send BBEdit an Apple event to make a new text window. This
- // will error if BBEdit is running, but the code to launch it
- // is an unnecessary complication. If you want to see logging,
- // you have to have BBEdit running.
-
- MoreAENullDesc(&theEvent);
- err = MoreAECreateAppleEventCreatorTarget(kAECoreSuite, kAECreateElement, kBBEditCreator, &theEvent);
- if (err == noErr) {
- cDoc = cDocument;
- err = AEPutParamPtr(&theEvent, keyAEObjectClass, typeType, &cDoc, sizeof(cDoc));
- }
- if (err == noErr) {
- err = AESend(&theEvent, &junkReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
- if (err == connectionInvalid) { // BBEdit not running
- err = noErr;
- }
- }
- MoreAEDisposeDesc(&theEvent);
- MoreAssertQ(err == noErr);
-
- }
- }
-
- extern pascal void BBLogSetState(Boolean logging)
- // See comment in header file.
- {
- gLogging = logging;
- }
-
- extern pascal void BBLogText(void *textPtr, Size textSize)
- // See comment in header file.
- {
- OSStatus err;
- AppleEvent theEvent;
- AppleEvent junkReply;
-
- MoreAssertQ(textPtr != nil);
-
- if (gLogging) {
-
- // Send BBEdit an insert text ('Nsrt') event. The text will go
- // into the front window, which is typically the window we created
- // during BBLogStart.
-
- MoreAENullDesc(&theEvent);
- err = MoreAECreateAppleEventCreatorTarget(kBBEditCreator, 'Nsrt', kBBEditCreator, &theEvent);
- if (err == noErr) {
- err = AEPutParamPtr(&theEvent, keyDirectObject, typeText, textPtr, textSize);
- }
- if (err == noErr) {
- err = AESend(&theEvent, &junkReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
- if (err == connectionInvalid) { // BBEdit not running
- err = noErr;
- }
- }
- MoreAEDisposeDesc(&theEvent);
- MoreAssertQ(err == noErr);
- }
- }
-
- static void BuildLineHeader(Str255 str)
- {
- UInt32 dateTime;
- Str255 tmpStr;
- static Str255 indentStr = "\p ";
-
- MoreAssertQ(str != nil);
-
- GetDateTime(&dateTime);
- TimeString(dateTime, true, tmpStr, nil);
- (void) PLstrcpy(str, tmpStr);
- (void) PLstrcat(str, "\p ");
- DateString(dateTime, shortDate, tmpStr, nil);
- (void) PLstrcat(str, tmpStr);
- (void) PLstrcat(str, "\p - ");
- indentStr[0] = gIndent * 2;
- (void) PLstrcat(str, indentStr);
- }
-
- extern pascal void BBLogLine(ConstStr255Param str)
- // See comment in header file.
- {
- Str255 tmpStr;
-
- MoreAssertQ(str != nil);
-
- if (gLogging) {
-
- // Add the date and time prefix, the appropriate indent, and the CR suffix.
-
- BuildLineHeader(tmpStr);
- (void) PLstrcat(tmpStr, str);
- (void) PLstrcat(tmpStr, "\p\r");
-
- BBLogText(&tmpStr[1], tmpStr[0]);
- }
- }
-
- extern pascal void BBLogIndent(void)
- // See comment in header file.
- {
- gIndent += 1;
- }
-
- extern pascal void BBLogOutdent(void)
- // See comment in header file.
- {
- MoreAssertQ(gIndent > 0);
- gIndent -= 1;
- }
-
- extern pascal void BBLogOutdentWithErr(OSStatus errNum)
- // See comment in header file.
- {
- Str255 tmpStr;
- Str255 tmpStr2;
-
- BBLogOutdent();
- if (gLogging) {
- if (errNum == noErr) {
- (void) PLstrcpy(tmpStr, "\perr=noErr");
- } else {
- (void) PLstrcpy(tmpStr, "\perr=");
- NumToString(errNum, tmpStr2);
- (void) PLstrcat(tmpStr, tmpStr2);
- }
- BBLogLine(tmpStr);
- }
- }
-
- extern pascal void BBLogAppleEvent(ConstStr255Param tag, const AppleEvent *theEvent)
- // See comment in header file.
- {
- OSStatus junk;
- AEEventClass classID;
- AEEventID eventID;
- DescType junkType;
- Size junkSize;
- Str255 tmpStr;
- Str255 tmpStr2;
-
- MoreAssertQ(tag != nil);
- MoreAssertQ(theEvent != nil);
-
- if (gLogging) {
-
- // Get the Apple event class and event IDs.
-
- classID = '????';
- junk = AEGetAttributePtr(theEvent, keyEventClassAttr, typeType, &junkType, &classID, sizeof(classID), &junkSize);
- MoreAssertQ(junk == noErr);
-
- eventID = '????';
- junk = AEGetAttributePtr(theEvent, keyEventIDAttr, typeType, &junkType, &eventID, sizeof(eventID), &junkSize);
- MoreAssertQ(junk == noErr);
-
- // Create a log string out of those IDs. Currently this
- // is the only information about the event that we log;
- // we might want to extend this in the future, with possibly
- // the parameter list (or at least the direct object).
-
- (void) PLstrcpy(tmpStr, tag);
- (void) PLstrcat(tmpStr, "\p='");
- tmpStr2[0] = 4;
- *((OSType *) &tmpStr2[1]) = classID;
- (void) PLstrcat(tmpStr, tmpStr2);
- (void) PLstrcat(tmpStr, "\p', '");
- tmpStr2[0] = 4;
- *((OSType *) &tmpStr2[1]) = eventID;
- (void) PLstrcat(tmpStr, tmpStr2);
- (void) PLstrcat(tmpStr, "\p'");
-
- BBLogLine(tmpStr);
- }
- }
-
- extern pascal void BBLogLong(ConstStr255Param tag, SInt32 l)
- // See comment in header file.
- {
- Str255 tmpStr;
- Str255 tmpStr2;
-
- MoreAssertQ(tag != nil);
-
- if (gLogging) {
- (void) PLstrcpy(tmpStr, tag);
- (void) PLstrcat(tmpStr, "\p=");
- NumToString(l, tmpStr2);
- (void) PLstrcat(tmpStr, tmpStr2);
-
- BBLogLine(tmpStr);
- }
- }
-
- extern pascal void BBLogDesc(ConstStr255Param tag, const AEDesc *desc)
- // See comment in header file.
- {
- OSStatus err;
- AEDesc coercedDesc;
- Str255 descStr;
- Str255 tmpStr;
- Handle descText;
-
- MoreAssertQ(tag != nil);
- MoreAssertQ(desc != nil);
-
- if (gLogging) {
- MoreAENullDesc(&coercedDesc);
- descText = nil;
-
- // First try coercing the descriptor to text.
- // If we succeed, then we use the resulting textual
- // description of the descriptor. If we fail,
- // we just log the descriptor type and size
-
- err = AECoerceDesc(desc, typeText, &coercedDesc);
- if (err == noErr) {
- err = MoreAECopyDescriptorDataToHandle(&coercedDesc, &descText);
-
- // If the original descriptor type was text, add
- // some “ ” around the text.
-
- if (err == noErr && desc->descriptorType == typeText) {
- (void) Munger(descText, 0, nil, 0, "“", 1);
- err = MemError();
-
- if (err == noErr) {
- err = PtrAndHand("”", descText, 1);
- }
- }
- } else {
- tmpStr[0] = 4;
- *((OSType *) &tmpStr[1]) = desc->descriptorType;
- (void) PLstrcpy(descStr, "\p'");
- (void) PLstrcat(descStr, tmpStr);
- (void) PLstrcat(descStr, "\p'");
- if (desc->dataHandle != nil) {
- (void) PLstrcat(descStr, "\p, size=");
- NumToString(AEGetDescDataSize(desc), tmpStr);
- (void) PLstrcat(descStr, tmpStr);
- }
- err = PtrToHand(&descStr[1], &descText, descStr[0]);
- }
-
- // Now that descText is set up to contain the textual
- // representation of desc, we just log it. We also
- // log the original type of the descriptor (in square
- // brackets).
-
- // First prepend the line header and the tag.
-
- if (err == noErr) {
- BuildLineHeader(tmpStr);
- (void) PLstrcat(tmpStr, tag);
- (void) PLstrcat(tmpStr, "\p=");
-
- (void) Munger(descText, 0, nil, 0, &tmpStr[1], tmpStr[0]);
- err = MemError();
- }
-
- // Then append the original descriptor type and the CR.
-
- if (err == noErr) {
- (void) PLstrcpy(tmpStr, "\p [");
- descStr[0] = 4;
- *((OSType *) &descStr[1]) = desc->descriptorType;
- (void) PLstrcat(tmpStr, descStr);
- (void) PLstrcat(tmpStr, "\p]\x0d");
-
- err = PtrAndHand(&tmpStr[1], descText, tmpStr[0]);
- }
-
- // Finally, log the text.
-
- if (err == noErr) {
- HLock(descText);
- BBLogText(*descText, GetHandleSize(descText));
- }
-
- // Clean up.
-
- if (descText != nil) {
- DisposeHandle(descText);
- MoreAssertQ(MemError() == noErr);
- }
- MoreAEDisposeDesc(&coercedDesc);
- }
- }
-
- extern pascal void BBLogDescType(ConstStr255Param tag, DescType theType)
- // See comment in header file.
- {
- Str255 tmpStr;
- Str255 tmpStr2;
-
- MoreAssertQ(tag != nil);
-
- if (gLogging) {
- (void) PLstrcpy(tmpStr, tag);
- (void) PLstrcat(tmpStr, "\p='");
- tmpStr2[0] = 4;
- *((OSType *) &tmpStr2[1]) = theType;
- (void) PLstrcat(tmpStr, tmpStr2);
- (void) PLstrcat(tmpStr, "\p'");
-
- BBLogLine(tmpStr);
- }
- }
-
- #endif // MORE_DEBUG
-